;!(function(document,window){
	var ck_tools = {};

    ck_tools.startWith = function(str,startStr){
        str = str.toString()
        if(!startStr){return false;}
        if(str.substring(0,startStr.length) == startStr){
          return true;
        }
        return false;
        /**
         * var reg=new RegExp("^"+str);
         * return reg.test(str);
        */
      }
    //首字母转为大写
    ck_tools.headWordToUpCase = function(str){
        return str.toLowerCase().replace(/\b(\w)|\s(\w)/g,function(word){return word.toUpperCase()})
    }
    //转为驼峰
    ck_tools.toF = function(str){
        return str.replace(/-\w/g,function(x) {
            return x.slice(1).toUpperCase();
        });
    };
     ck_tools.endWidth = function(str,endStr){
        str = str.toString()
        if(!endStr){return false;}
        if(str.substring(str.length-endStr.length) == endStr){
          return true;
        }
        return false;
        /**
         * var reg=new RegExp(str+"$");
         * return reg.test(this);
         *
         */
      }

	
	//数组拼接
	ck_tools.arrayConcact = function(arr1,arr2 = []){
		var newArr 
		try {//ES6
			newArr = arr.push(...arr2);
		}catch(err){
			newArr = arr.concat(arr2);
		}
		return newArr;
	}

    ck_tools.arrayConcact2 = function(){
            let otherArrays = this.arrayLike(arguments)
            ,targetArray = otherArrays.shift()
            ,otherArraysLen = otherArrays.length;
            for(let i=0; i<otherArraysLen; i++){
                try {//ES6
                    targetArray = arr.push(...otherArrays[i]);
                }catch(err){
                    targetArray = arr.concat(otherArrays[i]);
                }
            }
        }
	
	//（不改变数组内容）返回新数组
	ck_tools.returnNewArr = function(arr){
		return arr.slice();
	}
	
	//获取数组最大值
	ck_tools.getMax = function(arr){
		return Math.max.apply(null, arr);
	}
	
	//获取数组最小值
	ck_tools.getMin = function(arr){
		return Math.min.apply(null, arr);
	}
	
	/**
	 * 忽略字母大小写排序
	 * 参考链接：https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
	 * 返回值：返回新数组
	 * +false 等于0 +true 等于1
	 */
	ck_tools.wordIgnoreSort = function(arr){
		// 对需要排序的数字和位置的临时存储
		var mapped = arr.map(function(el, i) {
		  return { index: i, value: el.toLowerCase() };
		})
		// 按照多个值排序数组
		mapped.sort(function(a, b) {
		  return +(a.value > b.value) || +(a.value === b.value) - 1;
		});
		// 根据索引得到排序的结果
		var result = mapped.map(function(el){
		  return arr[el.index];
		});
		return result;
	}
	
	//按数值排序
	ck_tools.numSort = function(arr,desc){
		var compare = function(a,b){
			return desc === 'desc'? b-a : a-b;
		}
		//sort()返回原数组
		return arr.sort(compare);
	}
	
	/**
	 * 根据条件排序，适用于数组对象
	 * arr:待排序数组
	 * conditions：排序条件, 是一个数组
	 */
	ck_tools.conditionSort = function(arr,conditions){
		if(!conditions || !conditions.length){return arr}
		var length = conditions.length;			
		arr.sort(function(obj1,obj2){
			var i = 0 ;
			while(i<length){
				var req = conditions[i];
				if(obj1[req] > obj2[req]){
					return 1;
				}
				if(obj1[req] < obj2[req]){
					return -1;
				}
				if(i+1 < length){i++;continue;}
				return 0;
			}
		});
		return arr;
	}
	
	
	//伪数组转真数组
	ck_tools.ArrayLike = function(arrayLike){
		return Array.from ? Array.from(arrayLike) : Array.prototype.slice.call(arrayLike);
	}	

	//判断是否是数组
	ck_tools.isArray = function(arr){
		return Array.isArray ? Array.isArray(arr) : Object.prototype.toString.call(arr) == '[object Array]';
	};

	ck_tools.inArrayCom = function(arr,val){
		for(let len = arr.length, i = 0; i < len ; i++){
			if(arr[i] == val){
				return true;
			}
			return false;
		}
	}

	//判读元素是否在数组中
	//Array.indexOf返回元素在数组的索引值
	ck_tools.inArray = function(arr,val){
		return Array.indexOf ? (arr.indexOf(val) > -1 ? true : false) : ck_tools.inArrayCom(arr,val)
	}

	//判读元素是否在数组中
	//Array.includes 在返回true, 反之false
	ck_tools.isInArray = function(arr,val){
		Array.includes ? arr.includes(val) : ck_tools.inArrayCom(arr,val);
	}
	
	//数组去重
	ck_tools.uniqueArr = function(arr1, arr2) {
		let arr = arr1.concat(arr2||[])
		let result = []
		let obj = {}
		for (let i of arr) {
			if (i && !obj[i]) {
				result.push(i)
				obj[i] = 1
			}
		}
		return result
	}

	//只有IE不支持
	ck_tools.unique = function(arr){
		return Array.from(new Set(arr));
	}
	
	//删除数组中指定值
	ck_tools.delEleInArray = function(arr,val){
		return arr.splice(arr.indexOf(val),1);
	}
	

	//判断是否是对象
	ck_tools.isObj = function(obj){
		return Object.prototype.toString.call(obj) == '[object Object]';
	}

	//判断空对象
	ck_tools.isEmptyObj = function(obj){
		if(JSON.stringify(obj) == '{}'){
			return true;
		}
		return false;
	}

	//判读是否是函数，不对dom方法判读
	ck_tools.isFunction = function(){
		return typeof obj === "function" && typeof obj.nodeType !== "number";
	}

	//是否是window对象
	ck_tools.isWindow = function( obj ) {
		return obj != null && obj === obj.window;
	};

	//判读是否是自身属性
	ck_tools.isHasPro = function(obj,pro){
		return obj.hasOwnProperty(pro);  
	}

	/**
		判读是不是对象字面量(纯对象)。对象字面量创建方式有{}、new Object()创建  
	*/
	ck_tools.isPlainObject = function(obj){
		var flag = false;
		if(!obj || typeof obj != 'object'){return flag;}
		if(ck_tools.isHasPro(obj.constructor.prototype,"isPrototypeOf")){
			flag = true;
		}
		return flag;
	}

	//判读是否是字符串
	ck_tools.isString = function(str){
		return typeof str == 'string' || str instanceof String;
	}
    
    //基本数据类型判断
    function isBaseType(obj){
        const baseTypes= ["string","number","boolean","null","undefined","symbol"];
        if(baseTypes.indexOf(typeof(obj)) > -1 || (typeof obj == 'object' && obj == null)){
            return true;
        }
        return false;
    }

	//反转字符串
	ck_tools.reverseStr = function(str){
		return name.split("").reverse().join("");
	}
	
	/**
	 * 判读客户端
	 * */
    ck_tools.os = function(){
            let ua = navigator.userAgent,
                isWindowsPhone = /(?:Windows Phone)/.test(ua),			//手机版window
                isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone, //塞班
                isAndroid = /(?:Android)/.test(ua),				//安卓
                isIos = /\(i[^;]+;( U;)? CPU.+Mac OS X/.test(ua), 	//ios
                isIE = /(?:MSIE)/.test(ua),				//IE
                isFireFox = /(?:Firefox)/.test(ua),		//火狐
                isWexin = /(?:MicroMessenger)/i.test(ua),
                isChrome = /(?:Chrome|CriOS)/.test(ua),	//Chrome
                isPresto = /(?:Presto)/.test(ua),		//opera内核
                isTablet = /(?:iPad|PlayBook)/.test(ua) || (isAndroid && !/(?:Mobile)/.test(ua)) || (isFireFox && /(?:Tablet)/.test(ua)), //平板
                isIphone = /(?:iPhone)/.test(ua) && !isTablet,	//iPhone
                isPc = !isIphone && !isAndroid && !isSymbian && !isTablet && !isWindowsPhone, //pc
                isMobile = /AppleWebKit.*Mobile.*/.test(ua);
        return {
                isTablet: isTablet,
                isIphone: isIphone,
                isIos:isIos,
                isIE:isIE,
                isAndroid : isAndroid,
                isChrome: isChrome,
                isMobile:isMobile,
                isPc: isPc
        };
    }
     
    //获取IE版本
    ck_tools.IEV = function(){
            return navigator.userAgent.match(/(?:MSIE\s+(\d)+\.\d)/)[1];
    }
	
	/**
	 * 节流函数
	 * 参数说明
	 * handle:回调函数
	 * wait:节流时间
	 * nowExecute：是否立刻执行handle
	 * 参考链接：https://www.jianshu.com/p/f9f6b637fd6c、https://www.jianshu.com/p/f9f6b637fd6c
	*/
	ck_tools.throttle = function(handle,wait,nowExecute){
		var timer;
		return function(){
			var context = this
			,args = arguments;
			if (timer) {return;}
			timer = setTimeout(function(){
				handle.call(context,args);
				timer = null;
			},wait);
			if(!timer && nowExecute){
				handle.call(context,args);
			}
		};
	};
	
	/**
	 * 防抖函数
	 * 参数说明
	 * handle:回调函数
	 * wait:节流时间
	 * nowExecute：是否立刻执行handle
	*/
	ck_tools.debounce = function(handle,wait,nowExecute){
		var timer ;
		return function(){
			var context = this
			,args = arguments;
			if (timer) {clearTimeout(timer)}
			timer = setTimeout(function(){
				handle.call(context,args);
			},wait);
			if(!timer && nowExecute){
				handle.call(context,args);
			}
		}
	}

    /**
     * 防抖函数只会在最后执行一次，节流是每隔指定时间间隔执行一次
     * 
     */
	
	/**
	 * 监听窗口大小变化事件
	 */
	ck_tools.winResize = function (callback) {
		$(window).on('resize',debounce(callback,100,true));
	};
	
	/**
	 * 动画结束后的回调
	*/
	ck_tools.animationEnd = function(ele,type,sucHandle,errHandle){
		var _self = this;
		!type && (
			sucHandle = type,
			errHandle = sucHandle,
			type = 'animation'
		)
		//1、获取动画名
		var animateName = function(){
			var animteObj = {
				transition:{
					'transition':'transitionend',
					'OTransition':'oTransitionEnd',
					'MozTransition':'transitionend',
					'WebkitTransition':'webkitTransitionEnd'
				}
				,animation:{
					'animation': 'animationend',
					'OAnimation': 'oAnimationEnd',
					'MozAnimation': 'mozAnimationEnd',
					'WebkitAnimation': 'webkitAnimationEnd'
				}
			}
			var animateName = (function(el) {
				for (var t in animteObj[type]) {
					if (el.style[t] !== undefined) {
					  return animteObj[t];
					}
				}
			})(document.createElement('div'));
			return animateName;
		}();
		//2、给ele绑定动画结束的回调
		var animateEndEventListener = function(aniEndHandle){
			var called = false ;
			//在每次transitionEnd的事件后执行该函数
			var callback = function(ele){ 
				if (!called){
					called=true;
					aniEndHandle.call(_self,ele);
				}  
			};
			ele.addEventListener(animateName,function(){
				callback(ele);
				//通过setTimeout来补救windowphone中不触发事件的问题
				setTimeout(callback,100);
			},false);
		}
		if(animateName){
			animateEndEventListener(sucHandle(ele));
		}else{
			errHandle(ele);
		}
	};
	
	/**
	 * 简单节点转父子树
	 * 数据格式如下：
	 * var nodes =[
		{ id:1, pId:0, name:"随意勾选 1"},
		{ id:11, pId:1, name:"随意勾选 1-1"},
		{ id:111, pId:11, name:"随意勾选 1-1-1"},
		{ id:112, pId:11, name:"随意勾选 1-1-2"},
		{ id:12, pId:1, name:"随意勾选 1-2"},
		{ id:121, pId:12, name:"随意勾选 1-2-1"},
		{ id:122, pId:12, name:"随意勾选 1-2-2"},
		{ id:2, pId:0, name:"随意勾选 2"},
		{ id:21, pId:2, name:"随意勾选 2-1"},
		{ id:22, pId:2, name:"随意勾选 2-2"},
		{ id:221, pId:22, name:"随意勾选 2-2-1"},
		{ id:222, pId:22, name:"随意勾选 2-2-2"},
		{ id:23, pId:2, name:"随意勾选 2-3"}
	   ];
	*/
	ck_tools.parSubTree = function(nodes){
		// 删除所有 children属性,以防止多次调用
		jsonData.forEach(function(item){
			delete item.children;
		});
		// 将数据存储为 以id为 key 的'{}'对象
		var nodePoint = {},nodesLen = nodes.length;
		for(var i = 0; i < nodesLen;i++){
			nodePoint[nodes[i].id] = nodes[i];
		}
		//console.log(nodePoint)
		var node = [];
		for(var i = 0; i < nodesLen;i++){
			if(nodes[i].pId in nodePoint){//if(nodePoint[nodes[i].pId])
				(nodePoint[nodes[i].pId].children || (nodePoint[nodes[i].pId].children = [])).push(nodes[i]);
			}else{//不在则是顶级节点
				node.push(nodes[i]);
			}
		}
		return node;
	}
	
	/**
	 * 父子树转简单节点
	 * 参数：nodes简单节点数据同上格式
	 * childName：子节点属性名
	**/
	ck_tools.parSubTransformSimple = function(nodes,childName,pId){
        pId = pId ? pId:null;
		var childName = childName || 'children'
		,simpleNodes = [];
		for(var i = 0; i < nodes.length; i++){
			var node = nodes[i];
            node.pId = pId;
			simpleNodes.push(node);
			getchildNode(node)
		}
		return simpleNodes;
		function getchildNode(node){
			var childNode = node[childName];
			if(childNode){
				simpleNodes = simpleNodes.concat(parSubTransformSimple(childNode,childName,node.id));
			}
		}
	}
	
	ck_tools.forEach = function(array,iterate){
		var index = -1
		,length = array.length;
		while (++index < length) {
			iterate.call(this,array[index], index)
		}
		return array;
	}

	//对象属性深拷贝
	ck_tools.extend = function(){
		//arguments不能在箭头函数中使用
		if(arguments.length <= 0){return};
		var _self = this
		, args = ck_tools.ArrayLike(arguments)
		, target = args[0]
		, args = args.shift();
		ck_tools.forEach(args,function(arg,i){
			var keys = Object.keys(arg);
			ck_tools.forEach(keys,function(key,i){
				var val = arg[key];
				if(ck_tools.isPlainObject(val) || ck_tools.isArray(val)){
					var newTarget = ck_tools.isArray(val)?[]:{};
					//extend()返回给newTarget,再把newTarget值赋值给上一个目标对象 的key
					!target[key] ? target[key] = _self.extend(newTarget,val) : _self.extend(target[key],val)
				}else{
					target[key] = val;
				}
			});
		});
		return target;
	}

	//发布订阅函数（观察者模式）
	ck_tools.pubSub = function(){
		//保存所有的订阅事件 {Aevent:[pubfun(status,data),pubfun(status,data),...]}
		var subEvents = {}
		//订阅方法subscribe 类似于on / watcher
		, subscribe = function(eventType,handle){
			!eventType in subEvents && (subEvents[eventType] = [])
            subEvents[eventType].push(handle);
		}
		//发布函数publish 类似于trigger / observe
		, publish = function(eventType, ...data){
			eventType = subEvents[eventType];
            for (var i = 0; i < eventType.length; i++) {
                eventType[i].apply(this, data);
            }
		}
		//删除全部订阅
		, unSubscribe = function(eventType) {
			subEvents[eventType] && delete subEvents[eventType]
		}
		//通过handle删除指定订阅
		, unSubscribeByFun = function(eventType,handle){
			eventType = subEvents[eventType];
			if (eventType) {
				let handleIndex = eventType.indexOf(handle);
				if (handleIndex >= 0) {
					eventType.splice(handleIndex, 1);
				}
			}
		};
		return {
			on:subscribe,
			trigger:publish,
			off:unSubscribe,
			unSubscribeByFun:unSubscribeByFun
		};
	}

	//观察者模式
	ck_tools.observer = function(){
		//存放所有订阅者
		let subs = [];
		//发布者，有notify就是发布者
		const publish = {
			//添加观察者（订阅者）
			addSub(sub){
				subs.push(sub)
			},
			//通知订阅者的方法
			notify(){
				subs.forEach(sub=>{
					sub.update();
				})
			}
		}
		//观察者（订阅者）.有update就是观察者
		const watcher = {
			//接收通知的方法
			update(){
				
			}
		}
	}

	//---------------------------------------------获取查询字符串---------------------

	ck_tools.getQueryString = function(){
		const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
		const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
		let paramsObj = {};
		// 将 params 存到对象中
		paramsArr.forEach(param => {
			if (/=/.test(param)) { // 处理有 value 的参数
			let [key, val] = param.split('='); // 分割 key 和 value
			val = decodeURIComponent(val); // 解码 //加密：encodeURIComponent()
			val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字

			if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key，则添加一个值
				paramsObj[key] = [].concat(paramsObj[key], val);
			} else { // 如果对象没有这个 key，创建 key 并设置值
				paramsObj[key] = val;
			}
			} else { // 处理没有 value 的参数
			paramsObj[param] = true;
			}
  		})
  		return paramsObj;
	}

    ck_tools.GB2312UnicodeConverter = {
            //中文到Unicode
            ToUnicode: function (str) {
                var txt = escape(str).toLocaleLowerCase().replace(/%u/gi, '\\u');
                return txt.replace(/%7b/gi, '{').replace(/%7d/gi, '}').replace(/%3a/gi, ':').replace(/%2c/gi, ',').replace(/%27/gi, '\'').replace(/%22/gi, '"').replace(/%5b/gi, '[').replace(/%5d/gi, ']').replace(/%3D/gi, '=').replace(/%20/gi, ' ').replace(/%3E/gi, '>').replace(/%3C/gi, '<').replace(/%3F/gi, '?').replace(/%5c/gi, '\\');
            }
            //Unicode到中文
            , ToGB2312: function (str) {
                return unescape(str.trim().replace(/\\u/gi, '%u'));
            }
        }

	//---------------------------------------------Cookie-------------------------------------------------------------------------

	//分装cookie
	//使用链接：https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie
	var docCookies = {
	  getItem: function (sKey) {
		return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
	  },
	  setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
		if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
		var sExpires = "";
		if (vEnd) {
		  switch (vEnd.constructor) {
			case Number:
			  sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
			  break;
			case String:
			  sExpires = "; expires=" + vEnd;
			  break;
			case Date:
			  sExpires = "; expires=" + vEnd.toUTCString();
			  break;
		  }
		}
		document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
		return true;
	  },
	  removeItem: function (sKey, sPath, sDomain) {
		if (!sKey || !this.hasItem(sKey)) { return false; }
		document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + ( sDomain ? "; domain=" + sDomain : "") + ( sPath ? "; path=" + sPath : "");
		return true;
	  },
	  hasItem: function (sKey) {
		return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
	  },
	  keys: /* optional method: you can safely remove it! */ function () {
		var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
		for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
		return aKeys;
	  }
	};
	ck_tools.docCookies = docCookies;

	//----------------------------------------------Date-----------------------------------------------------------------------------

	var date = {
		//小于10补零
		addZero:function(num){
			return num > 9 ? num : "0"+num;
		}
		//格式化时间
		,formatDate:function(date,separate){ 
			if(!isString(separate) && separate != undefined){
				throw new Error("separate "+separate+" is not string type");
			}
			var separate = separate || '-';
			return date.getFullYear() + separate 
					+ addZero(date.getMonth() + 1)+ separate
					+ addZero(date.getDate())+" "
					+ addZero(date.getHours())+":"
					+ addZero(date.getMinutes())+":"
					+ addZero(date.getSeconds());
		}
		//获取date
		,getDate:function(dateStr){
			return new Date(dateStr);
		}
		//获取时间戳
		,getTimeStamp:function(date){
			return date.getTime();
		}
		//计算时间差
		,timeDifference:function(beginDateStr,endDateStr){
			var startTime = new Date(beginDateStr);
			var endTime = new Date(endDateStr);
			var date3= endTime.getTime() - startTime.getTime();
			var days = Math.round(date3/(24*3600*1000));
			return days;
		}
		/**
		* set多少天前/后的date
		* date：可以是（时间戳，格式化时间YYYY-MM-dd HH:mm:ss字符串，Date对象）
		*/
		,setManyDays:function(date,manyDays){
			date = new Date(date)
			date.setDate(date.getDate() + (manyDays));
			return date;
		}
		//获取指定年、月的天数
		,getDays:function(year, month){ 
			month = parseInt(month,10);
			var d= new Date(year,month,0);
			return d.getDate()
		}
        ,allDays: function(year: number) {
            let leapYear = false, sum_day = 0, month_arr = [4, 6, 9, 11];
            if (year % 100 === 0) { // 年份是整百
                leapYear = year % 400 === 0
            } else {
                leapYear = year % 4 === 0
            }
            // 下面计算每个月的天数
            for (let i = 1; i < 13; i++) {
                if (i === 2) {
                    sum_day += leapYear ? 29 : 28
                } else if (month_arr.includes(i)) {
                    sum_day += 30
                } else {
                    sum_day += 31
                }
            }
            return sum_day
        }
        ,hasDays:function(date) {
            // date减今年的第一天（xxxx年01月01日）
            const arr = date.split('-');
            const yearDate = new Date(arr[0], 0, 0);
            const curDate = new Date(arr[0], arr[1] - 1, arr[2], 0, 0, 0);
            // 86400000 = 24 * 60 * 60 * 1000  表示一天的时间
            const day = parseInt((curDate - yearDate) / 86400000);
            return day;
        }
		/**
		 * 计时器
		 * 参数：num 毫秒数
		*/
		,timer:function(num){
			const day = parseInt(num/(1000 * 3600 * 24));
            const hour = parseInt(num/(1000 * 3600))%24;
            const minute = parseInt(num/(1000 * 60))%60;
            const second = (num / 1000)%60;
			return this.addZero(hour)+":"+this.addZero(minute)+":"+this.addZero(second);
		}
        /**
         * 对时间戳进行时间格式化
         */
        ,timer2(num, unit = 1000){
            const day = parseInt(num/(unit * 3600 * 24));
            const hour = parseInt(num/(unit * 3600))%24;
            const minute = parseInt(num/(unit * 60))%60;
            const second = (num / unit)%60;
            return {
                day: this.addZero(day),
                hour: this.addZero(hour),
                minute: this.addZero(minute),
                second: this.addZero(second),
                num
            };
        }
		/* 例1：convertTime(10*1000)//10秒
		 * 例2：convertTime(28*60*1000)//28分钟
		 * 例3：convertTime(2*3600*1000)//2个小时
		 * 例4：convertTime(2*60*60*1000+28*60*1000+10*1000)//2小时 28分钟 10秒
		 * 例5：convertTime(2*3600*1000+3600*1000+60*1000)//3小时 1分钟 0秒
		*/
	};
	ck_tools.date = date;

	//----------------------------------------------table-----------------------------------------------------------------------------

	var table = {
		/**
		* 功能描述：行合并
		* table:合并的表格
		* startRow:起始行
		* endRow ：结束行
		* col：合并列的索引
		*/
		//表格行合并
       mergeTableRow:function(tableEl,startRow,endRow,col){
             if(endRow == 0){
                 //减1 表头只有一行，若表头有3行，则加3
                 endRow = tableEl.rows.length - 1 - 2;
             }
             if(endRow != startRow){
                  for(var i = startRow; i <= endRow; i++){
                       //加1 表头只有一行，若表头有3行，则加3
                       i != startRow ? tableEl.rows[i+2].deleteCell(col) : tableEl.rows[i+2].cells[col].rowSpan = (endRow-startRow)+1;  
                  }
             }
           return tableEl;
        }      
		/**
		* 功能描述：列合并
		* table:合并的表格
		* startRow:起始列
		* endRow ：结束列
		* col：合并行的索引
		*/
		,colSpan:function(table,startCol,endCol,row){
			if(endCol == 0){
				endCol = table.rows[row].cells.length - 1;
			}
			for(var i = endCol ; i>startCol;i--){
				//加1 表头只有一行，若表头有3行，则加3
				table.rows[row+1].removeChild(table.rows[row+1].cells[i]);
				table.rows[row+1].cells[startCol].colSpan +=1;
			}
			return table;
		}
		/*
		 * 获取指定行数据
		 */
		,getDataByRowIndex:function(table,rowIndex){
			var cells = ck_tools.ArrayLike(table.rows[rowIndex].cells);
			return cells.map(function(el){
				return el.innerHTML.trim();
			});
		}
		//滚动的表格信息窗体
		/**
		 * difVal:是表格容器table-rollable-container与表格table-rollable之间的差值
		 * qq收藏里 （滚动的表格信息窗体） 有例子
		*/
		,tableRollAble = function (difVal) {
			var tableConHeight = $(".table-rollable-container").height() - difVal ,interval = null;
			$(".table-rollable").each(function (i,item) {
				var $this = $(this)
				,tableHeight = $this.height();
				if(tableHeight > tableConHeight){
					autoScroll($this)
					$this.hover(function(){
						clearInterval($this.attr('interval'));
					},function(){
						autoScroll($this)
					})
				}
			});

			function autoScroll($table){
				clearInterval($table.attr('interval'));
				var curInterval = setInterval(function(){
					var $firstTr = $table.find("tr").first()
						,trHeight = $firstTr.outerHeight();
					$($table).animate({
						marginTop : -trHeight+"px"
					},500,function(){
						$(this).css({marginTop : "0"}).find("tr:first").appendTo(this);
					})
				},2000);
				$table.attr("interval",curInterval)
			}
		}
		/*<div class="table-rollable-container">  //添加此类指定表格容器table-rollable-container
			<table class="table-rollable"></table> //添加此类指定需要滚动的表格主体
		  </div>
		*/
	}
	ck_tools.table = table;
	
	
	//----------------------------------------------表单验证----------------------------------------------------------------------------	
	/**
	 * 使用方式---如下
	   ck_tools.validForm([
		{name:"ck",num:"12we",phone:"13211112222"}
		,{name:"ck%$",num:"12",phone:"13211112222"}
	   ],
	   {  
		 num:{"reg":/^[0-9]+$/,tip:"num字段格式有误！"}
		 //,name:{如上格式}
	   });
	*/
	ck_tools.validForm = function(validData,addValidFields){
		//内置正则
		var regs = {
	        "name":/^[\u4e00-\u9fa5a-zA-Z0-9]{2,50}$/
	        ,"phone":/^1[3456789]\d{9}$/
	        ,"num":/^[0-9]+$/
	        ,"*":/[\w\W]*/
	    },
		//内置tip提示
	    tip = {
	        "name":"名称格式不正确！"
	        ,"phone":"手机格式不正确！"
	        ,"lineName":"线路名称格式不正确！"
	        ,"tower":"杆塔编号格式不正确！"
	    },
		//内置验证的字段属性
	    validFields = {
	        name:{"reg":regs.name,tip:tip.name}
	        ,phone:{"reg":regs.phone,tip:tip.phone}
	        ,maxTower:{"reg":regs.num,"ignore":true,tip:tip.tower}
	        ,minTower:{"reg":regs.num,"ignore":true,tip:tip.tower}
	    }
		
		//核心方法 字段格式验证
		//返回的验证对象
		,validObj = {pass:true,error:null}
		,addValidFields = addValidFields || validFields;
		if(addValidFields != validFields){
			validFields = ck_tools.extend(validFields,addValidFields);
		}
		for(var i in validData){
			var fields = Object.keys(validData[i]);
			for(var j in fields){
				var vldField = fields[j];
				if(vldField in validFields){
					var validRule = validFields[vldField]
						,ignore = validRule.ignore || false
						,fieldVal = validData[i][fields[j]];
					if(!ignore || (ignore && fieldVal)){//不忽略验证
						if(!validRule.reg.test(fieldVal)){//若格式不正确
							validObj.pass = false;
							validObj.error = {};
							validObj.error.index = i;
							validObj.error.data = validData[i];
							validObj.error.field = vldField;
							if(!fieldVal){
								var tip = validRule.tip || "请填入信息！";
							}else {
								tip = validRule.tip || validObj.error.value+"-格式不正确！";
							}
							validObj.error.tip = tip;
							return validObj;
						}
					}
				}
			}
		}
		return validObj;
	};
	
	//----------------------------------------------dom方法----------------------------------------------------------------------------
	//参考链接：https://blog.csdn.net/w390058785/article/details/80461845
	//获取元素相对于html元素的偏移量
	ck_tools.offset = function(element){
		var offest = {
			top: 0,
			left: 0
		}
		,_position;
		getOffset(element, true);
		return offest;

		// 递归获取 offset, 可以考虑使用 getBoundingClientRect
		function getOffset(node, init) {
			// 非Element 终止递归
			if (node.nodeType !== 1) {return;}
			_position = window.getComputedStyle(node)['position'];
			// position=static: 继续递归父节点
			if (typeof(init) === 'undefined' && _position === 'static') {
				getOffset(node.parentNode);
				return;
			}
			offest.top = node.offsetTop + offest.top - node.scrollTop;
			offest.left = node.offsetLeft + offest.left - node.scrollLeft;
			// position = fixed: 获取值后退出递归
			if (_position === 'fixed') {return;}
			getOffset(node.parentNode);
		}
	}
	
	//判读鼠标滚轮在指定元素上滚动方向
	ck_tools.mousewheel = function(ele,fn){
		var toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];        //DomMouseScroll,MozMousePixelScroll都是为了兼容火狐
		if(ele.addEventListener){ //IE9+ , chrome   
			for(var i = toBind.length; i > 0; i--){
				ele.addEventListener(toBind[i-1],handleFun,false);
			}
		}else if(ele.attachEvent){ //IE 6/7/8
			ele.attachEvent('on'+toBind[0], handleFun);
		}else{
			ele.onmousewheel = handleFun;
		}
		function handleFun(e){
			var delta = 0
			,e = e || window.event;
			if(e.wheelDelta){ //IE 、chrome中向上滚动滚轮是120，反之，-120
				delta = e.wheelDelta; 
			}else if (e.deltaY){ //火狐中向上滚动滚轮是-3，反之，3
				delta = -e.deltaY;
			}else if( e.wheelDeltaY) { 
				delta = e.wheelDeltaY 
			}   
			//如果 delta == 0 说明浏览器不支持
			//if(!delta){return alert("您的浏览器版本，暂不支持滚轮滑动！！")};
			delta && typeof fn == 'function' && fn.call(ele,delta) 
		}
	}
	/**
		mousewheel(document.getElementById("chgImg"),function(delta){
			console.dir(delta);
		})	
	**/

	//给DOM元素扩展新方法
	ck_tools.extendDomMethod = function(method,impl){
		var implFunc = function(){impl.call(this)}
		if (window.HTMLElement) {
			// 使用原型扩展DOM自定义事件
			HTMLElement.prototype[method] = implFunc;
		} else {
			// 如果是不支持HTMLElement扩展的浏览器,通过遍历所有元素扩展DOM事件
			var allDom = document.all, allDomLeng = allDom.length;
			for (var i = 0; i < allDomLeng; i++) {
				allDom[i][method] = implFunc;
			}
		}
	}
    
    //DOMContentLoaded类似于JQuery的ready
    var ready = function(fn){
        var _self = this
        , eventListen = document.addEventListener
        , attachEvent = document.attachEvent
        , DOMContentLoaded = function(){
            //注销事件, 避免反复触发
            eventListen ? document.removeEventListener('DOMContentLoaded',DOMContentLoaded,false) : document.readyState == "complete" && document.detachEvent( "onreadystatechange", DOMContentLoaded);
            fn.call(_self); 
        };

        eventListen ? eventListen('DOMContentLoaed',DOMContentLoaded,false) : attachEvent('onreadystatechange',DOMContentLoaded);
            
        //不在iframe中
        if(document.documentElement.doScroll && !window.frameElement){
            try{
                document.documentElement.doScroll('left')
            }catch(err){
                return setTimeout(ready,5)
            }
            fn.call(_self);
        }
    }

	//获取浏览器或指定元素可视区域宽度
	ck_tools.getEleVisualAreaWidth = function(ele){
		return ele ? ele.clientWidth : document.documentElement.clientWidth || document.body.clientWidth;
	}

    ck_tools.getEleVisualAreaHeight = function(ele){
		return ele ? ele.clientHeight : document.documentElement.clientHeight || document.body.clientHeight;
	}
	
	//获取元素卷去的高度
	//Chrome里document.documentElement.scrollTop
	//非Chrome里document.body.scrollTop
	//Safari 比较特别，有自己获取scrollTop的函数：window.pageYOffset 
	ck_tools.getScrollTop = function(el){
        if(!el){
            return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
        }else{
            return el.scrollTop;
        }
	}

	//获取元素样式
	ck_tools.getStyle = function(style){
		return function(ele){
			return window.getComputedStyle ? window.getComputedStyle(ele)[style] : ele.currentStyle[style];
		}
	}
    //判断元素或者窗口的滚动条宽度
    let getScrollWidth = function(el,redirect){
        if(redirect!='x' || redirect!='y'){return;}
        redirect = redirect ? redirect : 'x'
        let attr = {
          'x':'Width'
          ,'y':'Height'
        }
        let clientWidth = ele ? ele['client'+attr[redirect]] : document.documentElement['client'+attr[redirect]] || document.body['client'+attr[redirect]];
        let scrollWidth = ele ? ele['scroll'+attr[redirect]] : window['inner'+attr[redirect]];
        return scrollWidth - clientWidth;
    }

    //判断是否有滚动条：y纵轴，x横轴
        function hasScrolled(ele,direction){
            if(direction==='y'){
                return ele.scrollHeight>ele.clientHeight;
            }else if(direction==='x'){
                return ele.scrollWidth>ele.clientWidth;
            }
        }


        //事件委托就是利用事件冒泡特性，给父元素绑定事件
        //parent.contains(child) 判断是否是某个节点的子节点
        //e.target 触发事件的源节点
        /*
        document.onclick = function(e){
            e = window.event || e;
            let parentApp = document.getElementById('app');
            if(parentApp.contains(e.target)){
                console.log("app元素内，移除.hide");
                document.querySelectorAll('.content')[0].classList.remove("hide")
            }else{
                console.log("app元素外，添加.hide");
                document.querySelectorAll('.content')[0].classList.add("hide")
            } 
        }
        //自定义contains方法
        var cusContains = function(parNode,childNode){
            //子节点不能是html或body标签
            while (childNode && !/HTML|BODY/.test(childNode.nodeName)){
                if (childNode == parNode){
                    return true;
                }
                childNode = childNode.parentNode;
            }
            return false;
        }
        */
    //多元素判断
    let containsClass = function(moutEl,targetEl){
        let moutEls = Array.from(document.querySelectorAll(moutEl));
        for(let i = 0,len = moutEls.length; i < len; i++){
            moutEl = moutEls[i]
            if(moutEl.contains(targetEl)){
                return true;
            }
        }
        return false;
    }
    /*
        $("#select-course").on({
            mouseover(e){
                if(!contains(".nav-item",e.target)) {
                    $(".nav-popup-item").stop(true, true).fadeOut(300)
                }
            }
        })

    */ 


    let insertAfter = function(newNode,targetNode){
        let parent = targetNode.parentNode;
           if(parent.lastChild == targetNode){
               //向指定父容器中追加子元素
               parent.appendChild(newNode)
            }else{
              //containerEl.innserBefore(newNode,targetNode)
              //在指定父容器中，将newNode追加至targetNode之前
              parent.innserBefore(newNode,targetNode.nextSibling);
       }
    }

     //元素替换
     //parentNode是oldNode.parentNode
     //parentNode.replaceChild(newNode,oldNode)
	
    //判断元素是否在元素可是范围内
    let isInClient = function(el){
        let clientHeight = ck_tools.getEleVisualAreaHeight()
        let top = el.getBoundingClientRect() && el.getBoundingClientRect().top
        if(top<clientHeight){
            console.log("加载元素")
            return true;
        }else{
            return false;
        }
    }


	//----------------------------------------------router--------------------------------------------------------------------------------
	
	//----------------------------------------------JS模板引擎----------------------------------------------------------------------------
	
	window.ck_tools = ck_tools;
})(document,this);






